using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Text.RegularExpressions;
using System.Windows.Forms;

using Banshee.Base;
using Banshee.MediaEngine;
using Banshee.Sources;
using Banshee.Configuration.Schema;
using Banshee.Plugins;
using Banshee.Winforms;
using Banshee.Base.Winforms.Widgets;

namespace Banshee
{
    //Cornel 23-03-2007 - I will try and stay as close to the GTK# UI as i can
    public partial class WindowPlayer : ComponentFactory.Krypton.Toolkit.KryptonForm
    {
        public static readonly uint SkipDelta = 10;
        public static readonly int VolumeDelta = 10;
        Hashtable playlistMenuMap = new Hashtable();
        private PlaylistModel playlistModel;
        Banshee.Base.Gui.SourceView sourceView;
        private SeekSlider seek_slider;
        private StreamPositionLabel stream_position_label;
        Banshee.Base.Winforms.Controls.SearchEntry searchEntry;
        public WindowPlayer()
        {
            InitializeComponent(); 
        }
        void InitSystem()
        {
            
            UpdateUI("Loading Banshee", 10);
            LogCore.PrintEntries = true;
            Globals.Initialize();
            Globals.StartupInitializer.Run();

            Globals.ShutdownRequested += new ShutdownRequestHandler(Globals_ShutdownRequested);
            UpdateUI("Creating Components", 60);
            BuildWindow();
            
        }
        private BackgroundWorker startupWorker = new BackgroundWorker();
        bool Globals_ShutdownRequested()
        {

            Banshee.Winforms.Controls.ActiveUserEventsManager.Instance.CancelAll();
            PlayerEngineCore.Dispose();
            return true;
        }
        ToolTip toolTips = new ToolTip();
        private void WindowPlayer_Load(object sender, EventArgs e)
        {

            InitSystem();
            IconThemeUtils.SetWindowIcon(this, Properties.Resources.music_player_banshee_22);
            
            this.Text = Banshee.Base.ConfigureDefines.PACKAGE + " " + Banshee.Base.ConfigureDefines.VERSION;

            startupfinished();
            Banshee.Controls.SplashScreen.CloseForm();
            this.BringToFront();
        }

        void SetTip(Control ctrl, string caption)
        {
            toolTips.SetToolTip(ctrl, caption);
        }
        void BuildWindow()
        {
            //mainMenu.Renderer = new GlassControls.Controls.Office2007Renderer();
            
            InterfaceElements.MainWindow = this;
            InterfaceElements.MainContainer = LibraryContainer;
            //SetTip(burn_button, "Write selection to CD");
            //SetTip(rip_button, Catalog.GetString("Import CD into library"));
            SetTip(previous_button, "Play previous song");
            SetTip(playpause_button, "Play/pause current song");
            SetTip(next_button, "Play next song");
            SetTip(dapDiskUsageBar, "Device disk usage");
            //SetTip(sync_dap_button, Catalog.GetString("Synchronize music library to device"));
            SetTip(volumeButton, "Adjust volume");
            SetTip(repeat_toggle_button, Catalog.GetString("Change repeat playback mode"));
            SetTip(shuffle_toggle_button, Catalog.GetString("Toggle shuffle playback mode"));
            SetTip(song_properties_button, Catalog.GetString("Edit and view metadata of selected songs"));
            playlistModel = new PlaylistModel();
            InterfaceElements.PlaylistView = playlistView;
            //playlistGrid.DataSource = new BindingList<TrackInfo>(playlistModel.Tracks);
            playlistView.LoadColumns();
            InterfaceElements.PlaylistContainer = playlistContainer;
            searchEntry = searchEntry1;
            Banshee.Winforms.Controls.ActiveUserEventsManager event_manager = new Banshee.Winforms.Controls.ActiveUserEventsManager();
            event_manager.Dock = DockStyle.Fill;
            event_manager.ControlAdded += new ControlEventHandler(event_manager_ControlAdded);
            event_manager.ControlRemoved += new ControlEventHandler(event_manager_ControlRemoved);
            event_panel.Controls.Add(event_manager);
            event_panel.Visible = false;
            trackInfoHeader.Title = "Banshee";
            trackInfoHeader.Dock = DockStyle.Fill;
            SetRepeatMode((RepeatMode)PlayerWindowSchema.PlaybackRepeat.Get());
            repeat_toggle_button.Values.Image = Properties.Resources.media_repeat_all;
            playpause_button.Values.Image = Properties.Resources.media_playback_start;
            sourceView = new Banshee.Base.Gui.SourceView();
            sourceView.Dock = DockStyle.Fill;
            sourceView.BringToFront();
            playlistView.SourceView = sourceView;
            SourceSplitter.Panel1.Controls.Add(sourceView);
            seek_slider = new SeekSlider();
            seek_slider.Dock = DockStyle.Fill;
            seek_slider.SeekRequested += new EventHandler(seek_slider_SeekRequested);
            seekpanel.Controls.Add(seek_slider);
            seek_slider.SetIdle();
            stream_position_label = new StreamPositionLabel(seek_slider);
            stream_position_label.Dock = DockStyle.Bottom;
            seekpanel.Controls.Add(stream_position_label);
            playlistModel.Repeat = RepeatMode.All;
            this.DoubleBuffered = true;
            InterfaceElements.SearchEntry = this.searchEntry1;
            InterfaceElements.ActionButtonBox = additional_action_buttons_box;
            SetupEventHandlers();
            Setrenderer(Properties.Settings.Default.style);
            
        }
        void UpdateUI(string status, int progress)
        {
            
            Banshee.Controls.SplashScreen.SetStatus(status, true,progress);
        }
        void playlist_grid_CellDoubleClick(object sender, DataGridViewCellEventArgs e)
        {
           // playlistView.PlayTrack();
        }

        void seek_slider_SeekRequested(object sender, EventArgs e)
        {
            PlayerEngineCore.Position = (uint)seek_slider.Value;
        }
        void SetupEventHandlers()
        {
           
            PlayerEngineCore.EventChanged += new PlayerEngineEventHandler(PlayerEngineCore_EventChanged);
            PlayerEngineCore.StateChanged += new PlayerEngineStateHandler(PlayerEngineCore_StateChanged);
            playlistModel.Updated += new EventHandler(playlistModel_Updated);
            searchEntry.Changed += new EventHandler(playlistView_Changed);
            SourceManager.ActiveSourceChanged += new SourceEventHandler(SourceManager_ActiveSourceChanged);
            SourceManager.SourceUpdated += new SourceEventHandler(SourceManager_SourceUpdated);
            SourceManager.SourceViewChanged += new SourceEventHandler(SourceManager_SourceViewChanged);
            SourceManager.SourceTrackAdded += new TrackEventHandler(SourceManager_SourceTrackAdded);
            SourceManager.SourceTrackRemoved += new TrackEventHandler(SourceManager_SourceTrackRemoved);
            Dap.DapCore.DapAdded += new Banshee.Dap.DapEventHandler(DapCore_DapAdded);
            
        }

        void DapCore_DapAdded(object o, Banshee.Dap.DapEventArgs args)
        {
            args.Dap.PropertiesChanged += new EventHandler(Dap_PropertiesChanged);
            args.Dap.SaveFinished += new EventHandler(Dap_SaveFinished);
        }

        void Dap_SaveFinished(object sender, EventArgs e)
        {
            if (SourceManager.ActiveSource is DapSource
            && !(SourceManager.ActiveSource as DapSource).IsSyncing)
            {
                playlistModel.ReloadSource();
                UpdateDapDiskUsageBar(SourceManager.ActiveSource as DapSource);
            }
            
        }

        void Dap_PropertiesChanged(object sender, EventArgs e)
        {
            
        }

        void SourceManager_SourceTrackRemoved(object o, TrackEventArgs args)
        {
            playlistView.RefreshTracks();
            sourceView.RefreshList();
        }

        void SourceManager_SourceTrackAdded(object o, TrackEventArgs args)
        {
            playlistView.RefreshTracks();
            sourceView.RefreshList();
        }

        void SourceManager_SourceViewChanged(SourceEventArgs args)
        {
            if (args.Source == SourceManager.ActiveSource)
            {
                UpdateSourceView();
            }
        }
        private void UpdateSourceView()
        {
            if (SourceManager.ActiveSource.ViewWidget != null)
            {
                ShowSourceWidget();
            }
            else
            {
                ShowPlaylistView();
            }
        }
        private void ShowSourceWidget()
        {

            this.BeginInvoke((MethodInvoker)delegate()
            {
                playlist_header_event_box.Visible = SourceManager.ActiveSource.ShowPlaylistHeader;

                if (LibraryContainer.Controls.Contains(SourceManager.ActiveSource.ViewWidget))
                {
                    return;
                }

                if (SourceManager.ActiveSource.ViewWidget == null)
                {
                    ShowPlaylistView();
                    return;
                }

                if (LibraryContainer.Controls.Count > 0)
                {
                    LibraryContainer.Controls.Clear();
                }

                LibraryContainer.Controls.Add(SourceManager.ActiveSource.ViewWidget);
            });
        }
        private void ShowPlaylistView()
        {

            if (LibraryContainer.Controls.Contains( playlistContainer))
            {
                return;
            }
            else if (LibraryContainer.Controls.Count >0 && LibraryContainer.Controls[0] != null)
            {
                LibraryContainer.Controls.Clear();
            }

            InterfaceElements.DetachPlaylistContainer();

            LibraryContainer.Controls.Add(playlistContainer);

            playlist_header_event_box.Visible = true;
        }
        void SourceManager_SourceUpdated(SourceEventArgs args)
        {
            if (args.Source == SourceManager.ActiveSource)
            {
                //UpdateViewName(args.Source);

                if (playlistModel.Count() == 0 && args.Source.Count > 0
                   && !searchEntry.IsQueryAvailable)
                {
                    playlistModel.ReloadSource();
                }
                searchEntry.Enabled = args.Source.SearchEnabled;
            }
        }

        void SourceManager_ActiveSourceChanged(SourceEventArgs args)
        {
            searchEntry.Ready = false;
            ThreadAssist.ProxyToMain(HandleSourceChanged);
            searchEntry.Ready = true;
        }
        Dap.DapDevice activedevice;
        void SourceChanged()
        {

                BeginInvoke((MethodInvoker)delegate() {
                    Application.DoEvents();// I hate using this but the app stutters when the library is big
                Source source = SourceManager.ActiveSource;
                if (source == null)
                {
                    return;
                }
                UpdateViewName(source, "Loading ...");
                playlistModel.ReloadSource();
                searchEntry.Ready = false;

                if (source.FilterQuery != null && source.FilterField != null)
                {
                    searchEntry.Query = source.FilterQuery;
                    searchEntry.Field = source.FilterField;
                }
                if (source is DapSource)
                {
                    DapSource dap_source = source as DapSource;
                    UpdateDapDiskUsageBar(dap_source);
                    dapDiskUsageBar.Visible = true;
                    sync_dap_button.Visible = true;
                    activedevice = dap_source.Device;

                    activedevice.SaveFinished += new EventHandler(Device_SaveFinished);
                }
                else
                {
                    dapDiskUsageBar.Visible = false;
                    sync_dap_button.Visible = false;
                    
                }
                UpdateViewName(source, string.Empty);
                // Bold label below track info
                // SensitizeActions(source); // Right-click actions, buttons above search

                // Make some choices for audio CDs, they can't be rated, nor have plays or
                // last-played info. Only show the rip button for audio CDs
                searchEntry.Enabled = source.SearchEnabled;
                //playlistView.RipColumn.Visible = source is AudioCdSource;

                UpdateSourceView();

                //OnPlaylistViewSelectionChanged(playlistView.Selection, new EventArgs());

                searchEntry.Ready = true;
            });
        }

        void Device_SaveFinished(object sender, EventArgs e)
        {
            if (SourceManager.ActiveSource is DapSource
            && !(SourceManager.ActiveSource as DapSource).IsSyncing)
            {
                playlistModel.ReloadSource();
                UpdateDapDiskUsageBar(SourceManager.ActiveSource as DapSource);
            }

            sourceView.RefreshList();
            playlistView.RefreshTracks();
        }
        private void UpdateDapDiskUsageBar(DapSource dapSource)
        {
            this.Invoke((MethodInvoker)delegate()
            {
                {
                    dapDiskUsageBar.Maximum = (int)dapSource.Device.StorageCapacity;
                    dapDiskUsageBar.Value = (int)dapSource.Device.StorageUsed;
                    dapDiskUsageBar.Text = dapSource.DiskUsageString;
                    string tooltip = dapSource.DiskUsageString + " (" + dapSource.DiskAvailableString + ")";
                    SetTip(dapDiskUsageBar, tooltip);
                }
            });
        }
        private void HandleSourceChanged(object o, EventArgs args)
        {
            ThreadAssist.Spawn(new System.Threading.ThreadStart(SourceChanged), true);
        }
        private void UpdateViewName(Source source,string info)
        {
            
            ViewNameLabel.Text = string.Format("{0} {1}",source.Name,info);
        }
        void playlistView_Changed(object sender, EventArgs e)
        {
            OnSimpleSearch(sender, e);
        }

        
        void playlistModel_Updated(object sender, EventArgs e)
        {
            UpdateStatusBar();
            sourceView.RefreshList();
        }
        private bool incrementedCurrentSongPlayCount;
        void PlayerEngineCore_StateChanged(object o, PlayerEngineStateArgs args)
        {
            switch (args.State)
            {
                case PlayerEngineState.Contacting:
                    stream_position_label.IsContacting = true;
                    seek_slider.SetIdle();
                    SetPlayButton();
                    break;
                case PlayerEngineState.Loaded:
                    incrementedCurrentSongPlayCount = false;
                    seek_slider.Duration = PlayerEngineCore.CurrentTrack.Duration.TotalSeconds;
                    UpdateMetaDisplay();

                    if (!PlayerEngineCore.CurrentTrack.CanPlay)
                    {
                        LogCore.Instance.PushWarning(
                            Catalog.GetString("Cannot Play Song"),
                            String.Format(Catalog.GetString("{0} cannot be played by Banshee. " +
                                "The most common reasons for this are:\n\n" +
                                "  u2022 Song is protected (DRM)\n" +
                                "  u2022 Song is on a DAP that does not support playback\n"),
                                PlayerEngineCore.CurrentTrack.Title));
                    }

                    break;
                case PlayerEngineState.Idle:
                    posTimer.Stop();
                    playpause_button.Values.Image = Properties.Resources.media_playback_start;
                    seek_slider.SetIdle();
                    trackInfoHeader.SetIdle();
                    stream_position_label.IsContacting = false;
                    UpdateMetaDisplay();

                    break;
                case PlayerEngineState.Paused:
                    posTimer.Stop();
                    playpause_button.Values.Image = Properties.Resources.media_playback_start;
                    break;
                case PlayerEngineState.Playing:
                   // posTimer.Start();
                    playlistView.SelectPlaying();
                    SetPlayButton();
                    UpdateMetaDisplay();
                    break;
            }
        }

        void PlayerEngineCore_EventChanged(object o, PlayerEngineEventArgs args)
        {
            switch (args.Event)
            {
                case PlayerEngineEvent.Iterate:
                   //Cornel - Although i have written the code ... the engine gets the event... but the event never fires here
                    OnPlayerEngineTick();
                    break;
                case PlayerEngineEvent.EndOfStream:
                   //ToggleAction action = Globals.ActionManager["StopWhenFinishedAction"] as ToggleAction;

                   /* if (!action.Active)
                    {
                        playlistModel.Continue();
                    }
                    else
                    {
                        //OnPlaylistStopped(null, null);
                    }*/
                    LogCore.Instance.PushInformation("Player Engine","Player Reached End of Stream");
                    playlistView.UpdateView();
                    Next();

                    break;
                case PlayerEngineEvent.StartOfStream:
                    UpdateMetaDisplay();
                    seek_slider.CanSeek = PlayerEngineCore.CanSeek;
                    break;
                case PlayerEngineEvent.Volume:
                   // volumeButton.Volume = PlayerEngineCore.Volume;
                    break;
                case PlayerEngineEvent.Buffering:
                    if (args.BufferingPercent >= 1.0)
                    {
                        stream_position_label.IsBuffering = false;
                        break;
                    }

                    stream_position_label.IsBuffering = true;
                    stream_position_label.BufferingProgress = args.BufferingPercent;
                    seek_slider.SetIdle();
                    break;
                case PlayerEngineEvent.Error:
                    Console.WriteLine("Player error");
                    RepeatMode old_repeat_mode = playlistModel.Repeat;
                    bool old_shuffle_mode = playlistModel.Shuffle;

                    playlistModel.Repeat = RepeatMode.ErrorHalt;
                    playlistModel.Shuffle = false;

                    Next();

                    playlistModel.Repeat = old_repeat_mode;
                    playlistModel.Shuffle = old_shuffle_mode;
                    break;
                case PlayerEngineEvent.TrackInfoUpdated:
                    UpdateMetaDisplay();
                    break;
            }
        }
        private void OnJumpToPlayingAction(object o, EventArgs args)
        {
            playlistView.ScrollToPlaying();
        }
        private void OnPlayerEngineTick()
        {
            
            uint stream_length = PlayerEngineCore.Length;
            uint stream_position = PlayerEngineCore.Position;

            stream_position_label.IsContacting = false;
            seek_slider.CanSeek = PlayerEngineCore.CanSeek;
            seek_slider.Duration = stream_length;
            seek_slider.SeekValue = stream_position;
            Console.WriteLine("Player Ticking");
            if (PlayerEngineCore.CurrentTrack == null)
            {
                return;
            }

            if (stream_length > 0 && PlayerEngineCore.CurrentTrack.Duration.TotalSeconds != (double)stream_length)
            {
                PlayerEngineCore.CurrentTrack.Duration = new TimeSpan(stream_length * TimeSpan.TicksPerSecond);
                PlayerEngineCore.CurrentTrack.Save();
            }

            if (stream_length > 0 && stream_position > stream_length / 2 && !incrementedCurrentSongPlayCount)
            {
                PlayerEngineCore.CurrentTrack.IncrementPlayCount();
                incrementedCurrentSongPlayCount = true;
            }
        }
        public void Previous()
        {
            playlistModel.Regress();
            playlistView.UpdateView();
        }
        public void Next()
        {
            playlistModel.Advance();
            playlistView.UpdateView();
        }
        public string ApplicationLongName
        {
            get { return Catalog.GetString("Banshee Music Player"); }
        }
        public void UpdateMetaDisplay()
        {
            TrackInfo track = PlayerEngineCore.CurrentTrack;

            if (track == null)
            {
                this.Text = ApplicationLongName;
                trackInfoHeader.Visible = false;
                cover_art_view.FileName = null;
                cover_art_view.BorderStyle = BorderStyle.None;
                //trackInfoHeader.Cover.Image = Properties.Resources.editor_cover_album;
                return;
            }

            trackInfoHeader.Artist = track.DisplayArtist;
            trackInfoHeader.Title = track.DisplayTitle;
            trackInfoHeader.Album = track.Album;
            trackInfoHeader.MoreInfoUri = track.MoreInfoUri != null ? track.MoreInfoUri.AbsoluteUri : null;
            trackInfoHeader.Visible = true;

            this.Text = track.DisplayTitle + ((track.Artist != null && track.Artist != String.Empty)
                ? (" (" + track.DisplayArtist + ")")
                : "");

            try
            {
                trackInfoHeader.FileName = track.CoverArtFileName;
                cover_art_view.FileName = track.CoverArtFileName;
                trackInfoHeader.Label = String.Format("{0} - {1}", track.DisplayArtist, track.DisplayAlbum);
                cover_art_view.Enabled = false;
            }
            catch (Exception)
            {
            }

        }
        void event_manager_ControlRemoved(object sender, ControlEventArgs e)
        {
            event_panel.Visible = false;
        }

        void event_manager_ControlAdded(object sender, ControlEventArgs e)
        {
            event_panel.Visible = true;
        }
        void startupfinished()
        {
            UpdateUI("Checking Startup status", 80);
            Application.DoEvents();
            if (Globals.Library.IsLoaded)
            {
                Library_Reloaded(Globals.Library, new EventArgs());
            }
            else
            {
                Globals.Library.Reloaded += new EventHandler(Library_Reloaded);
            }
            SourceManager.SetActiveSource(LibrarySource.Instance);
            Application.DoEvents();

            //Cornel Not using args right now
            /*if (LocalQueueSource.Instance.Count > 0)
            {
                SourceManager.SetActiveSource(LocalQueueSource.Instance);
            }*/
            /*foreach (Source source in SourceManager.Sources)
            {
                if (source is DapSource)
                {
                    DapSource dsource = source as DapSource;
                    
                }
            }*/
            UpdateUI("Loading Playlists", 90);
            Banshee.Base.HalCore.Control = this;
            playlistView.Model = playlistModel;
            Application.DoEvents();
            
        }
        protected override void WndProc(ref Message m)
        {
            base.WndProc(ref m);
                Banshee.Base.HalCore.SendMessage(ref m);
        }
        void Library_Reloaded(object sender, EventArgs e)
        {
            BeginInvoke((MethodInvoker)delegate() {
            if (Globals.Library.Tracks.Count <= 0)
            {
                    PromptForImport();
            }else
                sourceView.RefreshList();
            });

        }
        private void PromptForImport()
        {
            PromptForImport(true);
        }

        private void PromptForImport(bool startup)
        {
            bool show_dialog = System.Convert.ToBoolean(ImportSchema.ShowInitialImportDialog.Get());
            if (startup && !show_dialog)
            {
                return;
            }
            Banshee.Winforms.ImportDialog dialog = new Banshee.Winforms.ImportDialog();
            dialog.DoNotShowAgain = (bool)ImportSchema.ShowInitialImportDialog.Get();
            DialogResult dr = dialog.ShowDialog(this);
            if (dr != DialogResult.OK)
                return;
            else
            {
                IImportSource import_source = dialog.ActiveSource;
                if (import_source != null)
                {
                    import_source.Import();
                    
                }
            }
            if (startup)
            {
                ImportSchema.ShowInitialImportDialog.Set(!dialog.DoNotShowAgain);
            }
        }
        void SetTitle(string text)
        {
                BeginInvoke((MethodInvoker)delegate() { 
                this.Text = text;});
        }
        string pluglist = string.Empty;
        private void WindowPlayer_Shown(object sender, EventArgs e)
        {
            

        }
        private void next_button_Click(object sender, EventArgs e)
        {
            Next();
        }
        private void SetPlayButton()
        {
            if (PlayerEngineCore.CanPause)
            {
                playpause_button.Values.Image = Properties.Resources.media_playback_pause;
            }
            else
            {
                playpause_button.Values.Image = Properties.Resources.media_playback_stop;
            }
        }
        private void previous_button_Click(object sender, EventArgs e)
        {
            Previous();
        }
        public void TogglePlaying()
        {
            if (PlayerEngineCore.CurrentState == PlayerEngineState.Playing)
            {
                PlayerEngineCore.Pause();
            }
            else
            {
                PlayerEngineCore.Play();
            }
        }

        public void PlayPause()
        {
            if (PlayerEngineCore.CurrentState != PlayerEngineState.Idle)
            {
                TogglePlaying();
            }
            else
            {
                if (SourceManager.ActiveSource.HandlesStartPlayback)
                {
                    SourceManager.ActiveSource.StartPlayback();
                    return;
                }

                if (!playlistView.PlaySelected())
                {
                    playlistModel.Advance();
                    playlistView.UpdateView();
                }
            }
        }
        private void playpause_button_Click(object sender, EventArgs e)
        {
            PlayPause();

        }

        private void WindowPlayer_FormClosing(object sender, FormClosingEventArgs e)
        {
            Application.Exit();
            
        }
        private void UpdateStatusBar()
        {
            BeginInvoke((MethodInvoker)delegate() {

            long count = playlistModel.Count();

            if (count == 0 && SourceManager.ActiveSource == null)
            {
                LabelStatusBar.Text = ApplicationLongName;
                return;
            }
            else if (count == 0)
            {
                LabelStatusBar.Text = String.Empty;
                return;
            }

            TimeSpan span = playlistModel.TotalDuration;
            StringBuilder builder = new StringBuilder();

            builder.AppendFormat("{0} Items", count);
            builder.Append(", ");

            if (span.Days > 0)
            {
                builder.AppendFormat("{0} days", span.Days);
                builder.Append(", ");
            }

            if (span.Hours > 0)
            {
                builder.AppendFormat("{0} hours", span.Hours);
                builder.Append(", ");
            }

            builder.AppendFormat("{0} minutes", span.Minutes);
            builder.Append(", ");
            builder.AppendFormat("{0} seconds", span.Seconds);

            LabelStatusBar.Text = builder.ToString();
            });
        }
        private bool suspendSearch;
        private void OnSimpleSearch(object o, EventArgs args)
        {
            //Cornel - I found the BackgroundWorker gives me the most responsive UI
                UpdateViewName(SourceManager.ActiveSource, "Searching...");
                SourceManager.ActiveSource.FilterField = searchEntry.Field;
                SourceManager.ActiveSource.FilterQuery = searchEntry.Query;
                Source source = SourceManager.ActiveSource;

                if (SourceManager.ActiveSource.HandlesSearch)
                {
                    return;
                }

                if (suspendSearch)
                {
                    return;
                }

                playlistModel.ClearModel();

                if (!searchEntry.IsQueryAvailable)
                {
                    playlistModel.ReloadSource();

                    playlistView.UpdateView();
                    return;
                }
                this.backgroundWorker1.RunWorkerAsync();

                
                playlistView.UpdateView();
        }
        private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
        {
            lock (SourceManager.ActiveSource.TracksMutex)
            {
                foreach (TrackInfo track in SourceManager.ActiveSource.Tracks)
                {
                    try
                    {
                        if (DoesTrackMatchSearch(track))
                        {
                            playlistModel.AddTrack(track);
                        }
                    }
                    catch (Exception)
                    {
                        continue;
                    }
                }
            }
        }
        private bool DoesTrackMatchSearch(TrackInfo ti)
        {
            if (!searchEntry.IsQueryAvailable)
            {
                return false;
            }

            string query = searchEntry.Query;
            string field = searchEntry.Field;
            string[] matches;

            if (field == Catalog.GetString("Artist Name"))
            {
                matches = new string[] { ti.Artist };
            }
            else if (field == Catalog.GetString("Song Name"))
            {
                matches = new string[] { ti.Title };
            }
            else if (field == Catalog.GetString("Album Title"))
            {
                matches = new string[] { ti.Album };
            }
            else if (field == Catalog.GetString("Genre"))
            {
                matches = new string[] { ti.Genre };
            }
            else if (field == Catalog.GetString("Year"))
            {
                matches = new string[] { ti.Year.ToString() };
            }
            else
            {
                matches = new string[] {
                    ti.Artist,
                    ti.Album,
                    ti.Title,
                    ti.Genre,
                    ti.Year.ToString()
                };
            }

            List<string> words_include = new List<string>();
            List<string> words_exclude = new List<string>();

            Array.ForEach<string>(Regex.Split(query, @"\s+"), delegate(string word)
            {
                bool exclude = word.StartsWith("-");
                if (exclude && word.Length > 1)
                {
                    words_exclude.Add(word.Substring(1));
                }
                else if (!exclude)
                {
                    words_include.Add(word);
                }
            });

            foreach (string word in words_exclude)
            {
                foreach (string match in matches)
                {
                    if (match == null || match == String.Empty)
                    {
                        continue;
                    }

                    if (StringUtil.RelaxedIndexOf(match, word) >= 0)
                    {
                        return false;
                    }
                }
            }

            bool found;

            foreach (string word in words_include)
            {
                found = false;

                foreach (string match in matches)
                {
                    if (match == null || match == string.Empty)
                    {
                        continue;
                    }

                    if (StringUtil.RelaxedIndexOf(match, word) >= 0)
                    {
                        found = true;
                        break;
                    }
                }

                if (!found)
                {
                    return false;
                }
            }

            return true;
        }
        private void SetRepeatMode(RepeatMode mode)
        {
            playlistModel.Repeat = mode;
            PlayerWindowSchema.PlaybackRepeat.Set((int)mode);
            allToolStripMenuItem.Checked = mode == RepeatMode.All ? true : false;
            noneToolStripMenuItem.Checked = mode == RepeatMode.None ? true : false;
            singleToolStripMenuItem.Checked = mode == RepeatMode.Single ? true : false;
        }
        //Menu Functions

        private void importFolderToolStripMenuItem_Click(object sender, EventArgs e)
        {
            FolderImportSource.Instance.Import();
        }

        private void importFilesToolStripMenuItem_Click(object sender, EventArgs e)
        {
            FileImportSource.Instance.Import();
        }

        private void importMusicToolStripMenuItem_Click(object sender, EventArgs e)
        {
            PromptForImport(false);
        }

        private void quitToolStripMenuItem_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        private void selectAllToolStripMenuItem_Click(object sender, EventArgs e)
        {
            //TODO
        }

        private void selectNoneToolStripMenuItem_Click(object sender, EventArgs e)
        {
            //TODO
        }

        private void pluginsToolStripMenuItem_Click(object sender, EventArgs e)
        {
            //TODO
        }

        private void preferencesToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Banshee.Base.Winforms.Gui.PreferencesDialog prdlg = new Banshee.Base.Winforms.Gui.PreferencesDialog();
            prdlg.ShowDialog(this);
        }

        private void playToolStripMenuItem_Click(object sender, EventArgs e)
        {
            PlayPause();
        }

        private void previousToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (PlayerEngineCore.Position < 3)
            {
                Previous();
            }
            else
            {
                PlayerEngineCore.Position = 0;
            }
        }

        private void nextToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Next();
        }

        private void seekForwardToolStripMenuItem_Click(object sender, EventArgs e)
        {
            PlayerEngineCore.Position += SkipDelta;
        }

        private void seekBackwardToolStripMenuItem_Click(object sender, EventArgs e)
        {
            PlayerEngineCore.Position -= SkipDelta;
        }

        private void shuffleToolStripMenuItem_Click(object sender, EventArgs e)
        {
            //ToggleAction action = o as ToggleAction;
            //playlistModel.Shuffle = action.Active;
           //PlayerWindowSchema.PlaybackShuffle.Set(action.Active);
        }

        private void allToolStripMenuItem_Click(object sender, EventArgs e)
        {
            SetRepeatMode(RepeatMode.All);
            
        }

        private void noneToolStripMenuItem_Click(object sender, EventArgs e)
        {
            SetRepeatMode(RepeatMode.None);
        }

        private void singleToolStripMenuItem_Click(object sender, EventArgs e)
        {
            SetRepeatMode(RepeatMode.Single);
        }

        private void showCoverartToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (cover_art_view.Enabled)
            {
                cover_art_view.Enabled = false;
            }
            else
            {
                cover_art_view.Enabled = true;
            }
            showCoverartToolStripMenuItem.Checked = cover_art_view.Enabled;
        }

        private void showFullScreenToolStripMenuItem_Click(object sender, EventArgs e)
        {
           //Fullscreen 
        }

        private void showEqualiserToolStripMenuItem_Click(object sender, EventArgs e)
        {
            //Equaliser
        }

        private void columnsToolStripMenuItem_Click(object sender, EventArgs e)
        {
            playlistView.ColumnChooser();
        }
        //private Banshee.Gui.Dialogs.LogCoreDialog log_viewer = null;
        private void showLogToolStripMenuItem_Click(object sender, EventArgs e)
        {
           // playlistView.ShowPlugArea = true;
            //Show Logview
            /*
             if(log_viewer == null) {
                log_viewer = new Banshee.Gui.Dialogs.LogCoreDialog(LogCore.Instance, WindowPlayer);
                
                log_viewer.Response += delegate {
                    log_viewer.Hide();
                };
                
                log_viewer.DeleteEvent += delegate {
                    log_viewer.Destroy();
                    log_viewer = null;
                };
            }
            
            log_viewer.Show();
             */
        }
        private enum SearchTrackCriteria
        {
            Artist,
            Album,
            Genre
        }
        private void jumpToPlayingToolStripMenuItem_Click(object sender, EventArgs e)
        {
            playlistView.ScrollToPlaying();
            playlistView.SelectPlaying();
        }

        private void byAlbumToolStripMenuItem_Click(object sender, EventArgs e)
        {
            SearchBySelectedTrack(SearchTrackCriteria.Artist);
        }

        private void byArtistToolStripMenuItem_Click(object sender, EventArgs e)
        {
            SearchBySelectedTrack(SearchTrackCriteria.Artist);
        }

        private void byGenreToolStripMenuItem_Click(object sender, EventArgs e)
        {
            SearchBySelectedTrack(SearchTrackCriteria.Artist);
        }
        private void SearchBySelectedTrack(SearchTrackCriteria criteria)
        {
            //TODO Cornel fix this in the morning
            /*if (playlistView.Selection.CountSelectedRows() <= 0)
            {
                return;
            }
            */
            TrackInfo track = playlistModel.SelectedTrack;

            if (track == null)
            {
                return;
            }

            // suspend the search functionality (for performance reasons)
            suspendSearch = true;

            switch (criteria)
            {
                case SearchTrackCriteria.Album:
                    this.searchEntry.Field = Catalog.GetString("Album Title");
                    searchEntry.Query = track.Album;
                    break;
                case SearchTrackCriteria.Artist:
                    searchEntry.Field = Catalog.GetString("Artist Name");
                    searchEntry.Query = track.Artist;
                    break;
                case SearchTrackCriteria.Genre:
                    searchEntry.Field = Catalog.GetString("Genre");
                    searchEntry.Query = track.Genre;
                    break;
            } suspendSearch = false;
            OnSimpleSearch(this, null);


            playlistView.Select();
        }

        private void versionInfoToolStripMenuItem_Click(object sender, EventArgs e)
        {
            //Banshee.Gui.Dialogs.VersionInformationDialog dialog = new Banshee.Gui.Dialogs.VersionInformationDialog();

        }

        private void aboutToolStripMenuItem_Click(object sender, EventArgs e)
        {
            //Banshee.Gui.Dialogs.AboutDialog about = new Banshee.Gui.Dialogs.AboutDialog();
        }

        private void event_panel_VisibleChanged(object sender, EventArgs e)
        {
            if(sourceView != null)
                sourceView.BringToFront();
        }

        private void propertiesToolStripMenuItem_Click(object sender, EventArgs e)
        {

        }

        private void button3_Click(object sender, EventArgs e)
        {
            Banshee.Base.Gui.Dialogs.TrackEditor propEdit = new Banshee.Base.Gui.Dialogs.TrackEditor(playlistView.SelectedTrackInfoMultiple);
            propEdit.ShowDialog(this);
            playlistView.Refresh();
        }

        private void shuffle_toggle_button_Click(object sender, EventArgs e)
        {
            if (playlistModel.Shuffle)
            {
                playlistModel.Shuffle = false;
                shuffle_toggle_button.Values.Image = Properties.Resources.media_playlist_continuous;
            }
            else
            {
                playlistModel.Shuffle = true;
                shuffle_toggle_button.Values.Image = Properties.Resources.media_playlist_shuffle;
            }
        }

        private void repeat_toggle_button_Click(object sender, EventArgs e)
        {
            if (playlistModel.Repeat == RepeatMode.All)
            {
                SetRepeatMode(RepeatMode.Single);
                repeat_toggle_button.Values.Image = Properties.Resources.media_repeat_single;
            }
            else if (playlistModel.Repeat == RepeatMode.Single)
            {
                SetRepeatMode(RepeatMode.None);
                repeat_toggle_button.Values.Image = Properties.Resources.media_repeat_none;
            }
            else if(playlistModel.Repeat == RepeatMode.None)
            {
                SetRepeatMode(RepeatMode.All);
                repeat_toggle_button.Values.Image = Properties.Resources.media_repeat_all;
            }
        }
        private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            UpdateViewName(SourceManager.ActiveSource, string.Format("{0} out of {1} results for '{2}'", playlistModel.Count(), SourceManager.ActiveSource.Count, SourceManager.ActiveSource.FilterQuery));

        }

        private void SourceSplitter_Panel1_Resize(object sender, EventArgs e)
        {
            cover_art_view.Height = cover_art_view.Width;
        }

        private void sync_dap_button_Click(object sender, EventArgs e)
        {
            if (SourceManager.ActiveSource is DapSource)
            {
                DapSource source = (DapSource)SourceManager.ActiveSource;
                source.Device.Save();
            }
        }

        private void blueToolStripMenuItem_Click(object sender, EventArgs e)
        {
            
                Setrenderer(((ToolStripMenuItem)sender).Text);
        }
        void Setrenderer(string style)
        {
            switch (style)
            {
                case "Blue":
                    Manager.GlobalPaletteMode = ComponentFactory.Krypton.Toolkit.PaletteModeManager.Office2007Blue;
                    blueToolStripMenuItem.Checked = true;
                    silverToolStripMenuItem.Checked = false;
                    blackToolStripMenuItem.Checked = false;
                    break;
                case "Silver":
                    Manager.GlobalPaletteMode = ComponentFactory.Krypton.Toolkit.PaletteModeManager.Office2007Silver;
                    blueToolStripMenuItem.Checked = false;
                    silverToolStripMenuItem.Checked = true;
                    blackToolStripMenuItem.Checked = false;
                    break;
                case "Black":
                    Manager.GlobalPaletteMode = ComponentFactory.Krypton.Toolkit.PaletteModeManager.Office2007Black;
                    blueToolStripMenuItem.Checked = false;
                    silverToolStripMenuItem.Checked = false;
                    blackToolStripMenuItem.Checked = true;
                    break;
            }
            Color back = Manager.GlobalPalette.GetBackColor1(ComponentFactory.Krypton.Toolkit.PaletteBackStyle.PanelClient, ComponentFactory.Krypton.Toolkit.PaletteState.Normal);
            Color fore = Manager.GlobalPalette.ColorTable.MenuItemText;
            playlist_header_event_box.BackColor = back;
            playlist_header_event_box.ForeColor = fore;
            seek_slider.ViewColor = back;
            Properties.Settings.Default.style = style;
            Properties.Settings.Default.Save();
        }

        private void kryptonPalette1_PalettePaint(object sender, ComponentFactory.Krypton.Toolkit.PaletteLayoutEventArgs e)
        {
            playlistView.Invalidate();
        }

        private void posTimer_Tick(object sender, EventArgs e)
        {
            Application.DoEvents();
            OnPlayerEngineTick();
        }

    }
}